home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / os / sprite / RCS / xdmcp.c,v < prev   
Encoding:
Text File  |  1990-02-15  |  27.9 KB  |  1,153 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     90.02.14.19.25.27;  author tve;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @Original X11R4 distribution
  17. @
  18.  
  19.  
  20.  
  21. 1.1
  22. log
  23. @Initial revision
  24. @
  25. text
  26. @/*
  27.  * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
  28.  *
  29.  * Permission to use, copy, modify, and distribute this software and its
  30.  * documentation for any purpose and without fee is hereby granted, provided
  31.  * that the above copyright notice appear in all copies and that both that
  32.  * copyright notice and this permission notice appear in supporting
  33.  * documentation, and that the name of N.C.D. not be used in advertising or
  34.  * publicity pertaining to distribution of the software without specific,
  35.  * written prior permission.  N.C.D. makes no representations about the
  36.  * suitability of this software for any purpose.  It is provided "as is"
  37.  * without express or implied warranty.
  38.  *
  39.  */
  40.  
  41. #include "Xos.h"
  42. #include <sys/param.h>
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <netdb.h>
  46. #include <stdio.h>
  47. #include "X.h"
  48. #include "Xmd.h"
  49. #include "misc.h"
  50. #include "osdep.h"
  51. #include "input.h"
  52. #include "opaque.h"
  53.  
  54. #ifdef XDMCP
  55. #include "Xdmcp.h"
  56.  
  57. extern int argcGlobal;
  58. extern char **argvGlobal;
  59. extern char *display;
  60. extern long EnabledDevices[];
  61. extern long AllClients[];
  62. extern char *defaultDisplayClass;
  63.  
  64. static int            xdmcpSocket, sessionSocket;
  65. static xdmcp_states        state;
  66. static struct sockaddr_in   req_sockaddr;
  67. static int            req_socklen;
  68. static CARD32            SessionID;
  69. static long            timeOutTime;
  70. static int            timeOutRtx;
  71. static long            defaultKeepaliveDormancy = XDM_DEF_DORMANCY;
  72. static long            keepaliveDormancy = XDM_DEF_DORMANCY;
  73. static CARD16            DisplayNumber;
  74. static xdmcp_states        XDM_INIT_STATE = XDM_OFF;
  75. #ifdef HASDES
  76. static char            *xdmAuthCookie;
  77. #endif
  78.  
  79. static XdmcpBuffer        buffer;
  80.  
  81. static struct sockaddr_in   ManagerAddress;
  82.  
  83. static get_manager_by_name(), get_xdmcp_sock();
  84.  
  85. static    receive_packet(), send_packet();
  86. static    timeout(), restart();
  87.  
  88. static    recv_willing_msg();
  89. static    recv_accept_msg(),    recv_decline_msg();
  90. static    recv_refuse_msg(),    recv_failed_msg();
  91. static    recv_alive_msg();
  92.  
  93. static    send_query_msg();
  94. static    send_request_msg();
  95. static    send_manage_msg();
  96. static    send_keepalive_msg();
  97.  
  98. static XdmcpFatal(), XdmcpWarning();
  99. static void XdmcpBlockHandler(), XdmcpWakeupHandler();
  100.  
  101. static short    xdm_udp_port = XDM_UDP_PORT;
  102. static Bool    OneSession = FALSE;
  103.  
  104. XdmcpUseMsg ()
  105. {
  106.     ErrorF("-query host-name       contact named host for XDMCP\n");
  107.     ErrorF("-broadcast             broadcast for XDMCP\n");
  108.     ErrorF("-indirect host-name    contact named host for indirect XDMCP\n");
  109.     ErrorF("-port port-num         UDP port number to send messages to\n");
  110.     ErrorF("-once                  Terminate server after one session\n");
  111.     ErrorF("-class display-class   specify display class to send in manage\n");
  112. #ifdef HASDES
  113.     ErrorF("-cookie xdm-auth-bits  specify the magic cookie for XDMCP\n");
  114. #endif
  115.     ErrorF("-displayID display-id  manufacturer display ID for request\n");
  116. }
  117.  
  118. int 
  119. XdmcpOptions(argc, argv, i)
  120.     int        argc, i;
  121.     char    **argv;
  122. {
  123.     if (strcmp(argv[i], "-query") == 0) {
  124.     get_manager_by_name(argc, argv, ++i);
  125.     XDM_INIT_STATE = XDM_QUERY;
  126.     AccessUsingXdmcp ();
  127.     return (i + 1);
  128.     }
  129.     if (strcmp(argv[i], "-broadcast") == 0) {
  130.     XDM_INIT_STATE = XDM_BROADCAST;
  131.     AccessUsingXdmcp ();
  132.     return (i + 1);
  133.     }
  134.     if (strcmp(argv[i], "-indirect") == 0) {
  135.     get_manager_by_name(argc, argv, ++i);
  136.     XDM_INIT_STATE = XDM_INDIRECT;
  137.     AccessUsingXdmcp ();
  138.     return (i + 1);
  139.     }
  140.     if (strcmp(argv[i], "-port") == 0) {
  141.     ++i;
  142.     xdm_udp_port = atoi(argv[i]);
  143.     return (i + 1);
  144.     }
  145.     if (strcmp(argv[i], "-once") == 0) {
  146.     OneSession = TRUE;
  147.     return (i + 1);
  148.     }
  149.     if (strcmp(argv[i], "-class") == 0) {
  150.     ++i;
  151.     defaultDisplayClass = argv[i];
  152.     return (i + 1);
  153.     }
  154. #ifdef HASDES
  155.     if (strcmp(argv[i], "-cookie") == 0) {
  156.     ++i;
  157.     xdmAuthCookie = argv[i];
  158.     return (i + 1);
  159.     }
  160. #endif
  161.     if (strcmp(argv[i], "-displayID") == 0) {
  162.     ++i;
  163.     XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i]));
  164.     return (i + 1);
  165.     }
  166.     return (i);
  167. }
  168.  
  169. /*
  170.  * This section is a collection of routines for
  171.  * registering server-specific data with the XDMCP
  172.  * state machine.
  173.  */
  174.  
  175.  
  176. /*
  177.  * Save all broadcast addresses away so BroadcastQuery
  178.  * packets get sent everywhere
  179.  */
  180.  
  181. #define MAX_BROADCAST    10
  182.  
  183. static struct sockaddr_in   BroadcastAddresses[MAX_BROADCAST];
  184. static int            NumBroadcastAddresses;
  185.  
  186. XdmcpRegisterBroadcastAddress (addr)
  187.     struct sockaddr_in    *addr;
  188. {
  189.     struct sockaddr_in    *bcast;
  190.     if (NumBroadcastAddresses >= MAX_BROADCAST)
  191.     return;
  192.     bcast = &BroadcastAddresses[NumBroadcastAddresses++];
  193.     bzero (bcast, sizeof (struct sockaddr_in));
  194.     bcast->sin_family = addr->sin_family;
  195.     bcast->sin_port = htons (xdm_udp_port);
  196.     bcast->sin_addr = addr->sin_addr;
  197. }
  198.  
  199. /*
  200.  * Each authentication type is registered here; Validator
  201.  * will be called to check all access attempts using
  202.  * the specified authentication type
  203.  */
  204.  
  205. static ARRAYofARRAY8    AuthenticationNames, AuthenticationDatas;
  206. typedef struct _AuthenticationFuncs {
  207.     Bool    (*Validator)();
  208.     Bool    (*Generator)();
  209.     Bool    (*AddAuth)();
  210. } AuthenticationFuncsRec, *AuthenticationFuncsPtr;
  211.  
  212. static AuthenticationFuncsPtr    AuthenticationFuncsList;
  213.  
  214. XdmcpRegisterAuthentication (name, namelen, data, datalen, Validator, Generator, AddAuth)
  215.     char    *name;
  216.     int        namelen;
  217.     char    *data;
  218.     int        datalen;
  219.     Bool    (*Validator)();
  220.     Bool    (*Generator)();
  221.     Bool    (*AddAuth)();
  222. {
  223.     int        i;
  224.     ARRAY8  AuthenticationName, AuthenticationData;
  225.     static AuthenticationFuncsPtr    newFuncs;
  226.  
  227.     if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen))
  228.     return;
  229.     if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen))
  230.     {
  231.     XdmcpDisposeARRAY8 (&AuthenticationName);
  232.     return;
  233.     }
  234.     for (i = 0; i < namelen; i++)
  235.     AuthenticationName.data[i] = name[i];
  236.     for (i = 0; i < datalen; i++)
  237.     AuthenticationData.data[i] = data[i];
  238.     if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
  239.                      AuthenticationNames.length + 1) &&
  240.       XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas,
  241.                      AuthenticationDatas.length + 1) &&
  242.       (newFuncs = (AuthenticationFuncsPtr) xalloc (
  243.             (AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec)))))
  244.     {
  245.     XdmcpDisposeARRAY8 (&AuthenticationName);
  246.     XdmcpDisposeARRAY8 (&AuthenticationData);
  247.     return;
  248.     }
  249.     for (i = 0; i < AuthenticationNames.length - 1; i++)
  250.     newFuncs[i] = AuthenticationFuncsList[i];
  251.     newFuncs[AuthenticationNames.length-1].Validator = Validator;
  252.     newFuncs[AuthenticationNames.length-1].Generator = Generator;
  253.     newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth;
  254.     xfree (AuthenticationFuncsList);
  255.     AuthenticationFuncsList = newFuncs;
  256.     AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName;
  257.     AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData;
  258. }
  259.  
  260. /*
  261.  * Select the authentication type to be used; this is
  262.  * set by the manager of the host to be connected to.
  263.  */
  264.  
  265. ARRAY8        noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
  266. ARRAY8        noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
  267. ARRAY8Ptr    AuthenticationName = &noAuthenticationName;
  268. ARRAY8Ptr    AuthenticationData = &noAuthenticationData;
  269. AuthenticationFuncsPtr    AuthenticationFuncs;
  270.  
  271. XdmcpSetAuthentication (name)
  272.     ARRAY8Ptr    name;
  273. {
  274.     int    i;
  275.  
  276.     XdmcpDisposeARRAY8 (AuthenticationName);
  277.     for (i = 0; i < AuthenticationNames.length; i++)
  278.     if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name))
  279.     {
  280.         AuthenticationName = &AuthenticationNames.data[i];
  281.         AuthenticationData = &AuthenticationDatas.data[i];
  282.         AuthenticationFuncs = &AuthenticationFuncsList[i];
  283.         break;
  284.     }
  285. }
  286.  
  287. /*
  288.  * Register the host address for the display
  289.  */
  290.  
  291. static ARRAY16        ConnectionTypes;
  292. static ARRAYofARRAY8    ConnectionAddresses;
  293. static long        xdmcpGeneration;
  294.  
  295. XdmcpRegisterConnection (type, address, addrlen)
  296.     int        type;
  297.     char    *address;
  298.     int        addrlen;
  299. {
  300.     int        i;
  301.     CARD8   *newAddress;
  302.  
  303.     if (xdmcpGeneration != serverGeneration)
  304.     {
  305.     XdmcpDisposeARRAY16 (&ConnectionTypes);
  306.     XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses);
  307.     xdmcpGeneration = serverGeneration;
  308.     }
  309.     newAddress = (CARD8 *) xalloc (addrlen * sizeof (CARD8));
  310.     if (!newAddress)
  311.     return;
  312.     if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1))
  313.     {
  314.     xfree (newAddress);
  315.     return;
  316.     }
  317.     if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses,
  318.                     ConnectionAddresses.length +  1))
  319.     {
  320.     xfree (newAddress);
  321.     return;
  322.     }
  323.     ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
  324.     for (i = 0; i < addrlen; i++)
  325.     newAddress[i] = address[i];
  326.     ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress;
  327.     ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen;
  328. }
  329.  
  330. /*
  331.  * Register an Authorization Name.  XDMCP advertises this list
  332.  * to the manager.
  333.  */
  334.  
  335. static ARRAYofARRAY8    AuthorizationNames;
  336.  
  337. XdmcpRegisterAuthorizations ()
  338. {
  339.     XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames);
  340.     RegisterAuthorizations ();
  341. }
  342.  
  343. XdmcpRegisterAuthorization (name, namelen)
  344.     char    *name;
  345.     int        namelen;
  346. {
  347.     ARRAY8  authName;
  348.     int        i;
  349.  
  350.     authName.data = (CARD8 *) xalloc (namelen * sizeof (CARD8));
  351.     if (!authName.data)
  352.     return;
  353.     if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1))
  354.     {
  355.     xfree (authName.data);
  356.     return;
  357.     }
  358.     for (i = 0; i < namelen; i++)
  359.     authName.data[i] = (CARD8) name[i];
  360.     authName.length = namelen;
  361.     AuthorizationNames.data[AuthorizationNames.length-1] = authName;
  362. }
  363.  
  364. /*
  365.  * Register the DisplayClass string
  366.  */
  367.  
  368. ARRAY8    DisplayClass;
  369.  
  370. XdmcpRegisterDisplayClass (name, length)
  371.     char    *name;
  372.     int        length;
  373. {
  374.     int        i;
  375.  
  376.     XdmcpDisposeARRAY8 (&DisplayClass);
  377.     if (!XdmcpAllocARRAY8 (&DisplayClass, length))
  378.     return;
  379.     for (i = 0; i < length; i++)
  380.     DisplayClass.data[i] = (CARD8) name[i];
  381. }
  382.  
  383. /*
  384.  * Register the Manufacturer display ID
  385.  */
  386.  
  387. ARRAY8 ManufacturerDisplayID;
  388.  
  389. XdmcpRegisterManufacturerDisplayID (name, length)
  390.     char    *name;
  391.     int        length;
  392. {
  393.     int        i;
  394.  
  395.     XdmcpDisposeARRAY8 (&ManufacturerDisplayID);
  396.     if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length))
  397.     return;
  398.     for (i = 0; i < length; i++)
  399.     ManufacturerDisplayID.data[i] = (CARD8) name[i];
  400. }
  401.  
  402. /* 
  403.  * initialize XDMCP; create the socket, compute the display
  404.  * number, set up the state machine
  405.  */
  406.  
  407. void 
  408. XdmcpInit()
  409. {
  410.     state = XDM_INIT_STATE;
  411. #ifdef HASDES
  412.     if (xdmAuthCookie)
  413.     XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie));
  414. #endif
  415.     if (state != XDM_OFF)
  416.     {
  417.     XdmcpRegisterAuthorizations();
  418.     XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass));
  419.     AccessUsingXdmcp();
  420.     RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
  421.                         (pointer) 0);
  422.         timeOutRtx = 0;
  423.         DisplayNumber = (CARD16) atoi(display);
  424.         get_xdmcp_sock();
  425.         send_packet();
  426.     }
  427. }
  428.  
  429. void
  430. XdmcpReset ()
  431. {
  432.     state = XDM_INIT_STATE;
  433.     if (state != XDM_OFF)
  434.     {
  435.     RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
  436.                         (pointer) 0);
  437.         timeOutRtx = 0;
  438.         send_packet();
  439.     }
  440. }
  441.  
  442. /*
  443.  * Called whenever a new connection is created; notices the
  444.  * first connection and saves it to terminate the session
  445.  * when it is closed
  446.  */
  447.  
  448. void
  449. XdmcpOpenDisplay(sock)
  450.     int    sock;
  451. {
  452.     extern void AugmentSelf();
  453.  
  454.     if (state != XDM_AWAIT_MANAGE_RESPONSE)
  455.     return;
  456.     state = XDM_RUN_SESSION;
  457.     sessionSocket = sock;
  458.     /* permit access control manipulations from this host */
  459.     AugmentSelf(sock);
  460. }
  461.  
  462. void 
  463. XdmcpCloseDisplay(sock)
  464.     int    sock;
  465. {
  466.     if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
  467.     || sessionSocket != sock)
  468.         return;
  469.     state = XDM_INIT_STATE;
  470.     if (OneSession)
  471.     dispatchException |= DE_TERMINATE;
  472.     else
  473.     dispatchException |= DE_RESET;
  474.     isItTimeToYield = TRUE;
  475. }
  476.  
  477. /*
  478.  * called before going to sleep, this routine
  479.  * may modify the timeout value about to be sent
  480.  * to select; in this way XDMCP can do appropriate things
  481.  * dynamically while starting up
  482.  */
  483.  
  484. /*ARGSUSED*/
  485. static void
  486. XdmcpBlockHandler(data, wt, LastSelectMask)
  487.     pointer        data;   /* unused */
  488.     struct timeval  **wt;
  489.     long        *LastSelectMask;
  490. {
  491.     long millisToGo, wtMillis;
  492.     static struct timeval waittime;
  493.  
  494.     if (state == XDM_OFF)
  495.     return;
  496.     *LastSelectMask |= (1 << xdmcpSocket);
  497.     if (timeOutTime == 0)
  498.     return;
  499.     millisToGo = timeOutTime - GetTimeInMillis() + 1;
  500.     if (millisToGo < 0)
  501.     millisToGo = 0;
  502.     if (*wt == NULL)
  503.     {
  504.     waittime.tv_sec = (millisToGo) / 1000;
  505.     waittime.tv_usec = 1000 * (millisToGo % 1000);
  506.     *wt = &waittime;
  507.     }
  508.     else
  509.     {
  510.     wtMillis = (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000;
  511.     if (millisToGo < wtMillis)
  512.      {
  513.         (*wt)->tv_sec = (millisToGo) / 1000;
  514.         (*wt)->tv_usec = 1000 * (millisToGo % 1000);
  515.     }
  516.     }
  517. }
  518.  
  519. /*
  520.  * called after select returns; this routine will
  521.  * recognise when XDMCP packets await and
  522.  * process them appropriately
  523.  */
  524.  
  525. /*ARGSUSED*/
  526. static void
  527. XdmcpWakeupHandler(data, i, LastSelectMask)
  528.     pointer data;   /* unused */
  529.     int        i;
  530.     long    *LastSelectMask;
  531. {
  532.     long    devicesReadable[mskcnt];
  533.  
  534.     if (state == XDM_OFF)
  535.     return;
  536.     if (i > 0)
  537.     {
  538.     if (GETBIT(LastSelectMask, xdmcpSocket))
  539.     {
  540.         receive_packet();
  541.         BITCLEAR(LastSelectMask, xdmcpSocket);
  542.     } 
  543.     MASKANDSETBITS(devicesReadable, LastSelectMask, EnabledDevices);
  544.     if (ANYSET(devicesReadable))
  545.     {
  546.         if (state == XDM_AWAIT_USER_INPUT)
  547.         restart();
  548.         else if (state == XDM_RUN_SESSION)
  549.         keepaliveDormancy = defaultKeepaliveDormancy;
  550.     }
  551.     if (ANYSET(AllClients) && state == XDM_RUN_SESSION)
  552.         timeOutTime = GetTimeInMillis() +  keepaliveDormancy * 1000;
  553.     }
  554.     else if (timeOutTime && GetTimeInMillis() >= timeOutTime)
  555.     {
  556.         if (state == XDM_RUN_SESSION)
  557.         {
  558.         state = XDM_KEEPALIVE;
  559.         send_packet();
  560.         }
  561.         else
  562.         timeout();
  563.     }
  564. }
  565.  
  566. /*
  567.  * This routine should be called from the routine that drives the
  568.  * user's host menu when the user selects a host
  569.  */
  570.  
  571. XdmcpSelectHost(host_sockaddr, host_len, AuthenticationName)
  572.     struct sockaddr_in    *host_sockaddr;
  573.     int            host_len;
  574.     ARRAY8Ptr        AuthenticationName;
  575. {
  576.     state = XDM_START_CONNECTION;
  577.     bcopy(host_sockaddr, &req_sockaddr, host_len);
  578.     req_socklen = host_len;
  579.     XdmcpSetAuthentication (AuthenticationName);
  580.     send_packet();
  581. }
  582.  
  583. /*
  584.  * !!! this routine should be replaced by a routine that adds
  585.  * the host to the user's host menu. the current version just
  586.  * selects the first host to respond with willing message.
  587.  */
  588.  
  589. /*ARGSUSED*/
  590. XdmcpAddHost(from, fromlen, AuthenticationName, hostname, status)
  591.     struct sockaddr_in  *from;
  592.     ARRAY8Ptr        AuthenticationName, hostname, status;
  593. {
  594.     XdmcpSelectHost(from, fromlen, AuthenticationName);
  595. }
  596.  
  597. /*
  598.  * A message is queued on the socket; read it and
  599.  * do the appropriate thing
  600.  */
  601.  
  602. ARRAY8    UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
  603.  
  604. static
  605. receive_packet()
  606. {
  607.     struct sockaddr_in from;
  608.     int fromlen = sizeof(struct sockaddr_in);
  609.     XdmcpHeader    header;
  610.  
  611.     /* read message off socket */
  612.     if (!XdmcpFill (xdmcpSocket, &buffer, (struct sockaddr *) &from, &fromlen))
  613.     return;
  614.  
  615.     /* reset retransmission backoff */
  616.     timeOutRtx = 0;
  617.  
  618.     if (!XdmcpReadHeader (&buffer, &header))
  619.     return;
  620.  
  621.     if (header.version != XDM_PROTOCOL_VERSION)
  622.     return;
  623.  
  624.     switch (header.opcode) {
  625.     case WILLING:
  626.     recv_willing_msg(&from, fromlen, header.length);
  627.     break;
  628.     case UNWILLING:
  629.     XdmcpFatal("Manager unwilling", &UnwillingMessage);
  630.     break;
  631.     case ACCEPT:
  632.     recv_accept_msg(header.length);
  633.     break;
  634.     case DECLINE:
  635.     recv_decline_msg(header.length);
  636.     break;
  637.     case REFUSE:
  638.     recv_refuse_msg(header.length);
  639.     break;
  640.     case FAILED:
  641.     recv_failed_msg(header.length);
  642.     break;
  643.     case ALIVE:
  644.     recv_alive_msg(header.length);
  645.     break;
  646.     }
  647. }
  648.  
  649. /*
  650.  * send the appropriate message given the current state
  651.  */
  652.  
  653. static
  654. send_packet()
  655. {
  656.     switch (state) {
  657.     case XDM_QUERY:
  658.     case XDM_BROADCAST:
  659.     case XDM_INDIRECT:
  660.     send_query_msg();
  661.     break;
  662.     case XDM_START_CONNECTION:
  663.     send_request_msg();
  664.     break;
  665.     case XDM_MANAGE:
  666.     send_manage_msg();
  667.     break;
  668.     case XDM_KEEPALIVE:
  669.     send_keepalive_msg();
  670.     break;
  671.     }
  672.     timeOutTime = GetTimeInMillis() 
  673.     + MIN (XDM_MIN_RTX * (1 << timeOutRtx), XDM_MAX_RTX) * 1000;
  674. }
  675.  
  676. /*
  677.  * The session is declared dead for some reason; too many
  678.  * timeouts, or Keepalive failure.
  679.  */
  680.  
  681. XdmcpDeadSession (reason)
  682.     char *reason;
  683. {
  684.     printf ("XDM: %s, declaring session dead\n", reason);
  685.     state = XDM_INIT_STATE;
  686.     isItTimeToYield = TRUE;
  687.     dispatchException |= DE_RESET;
  688.     timeOutTime = 0;
  689.     timeOutRtx = 0;
  690.     send_packet();
  691. }
  692.  
  693. /*
  694.  * Timeout waiting for an XDMCP response.
  695.  */
  696.  
  697. static 
  698. timeout()
  699. {
  700.     timeOutRtx++;
  701.     if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT )
  702.     {
  703.     XdmcpDeadSession ("too many keepalive retransmissions");
  704.     return;
  705.     }
  706.     else if (timeOutRtx >= XDM_RTX_LIMIT)
  707.     {
  708.     printf("XDM: too many retransmissions\n");
  709.     state = XDM_AWAIT_USER_INPUT;
  710.     timeOutTime = 0;
  711.     timeOutRtx = 0;
  712.     return;
  713.     }
  714.  
  715.     switch (state) {
  716.     case XDM_COLLECT_QUERY:
  717.     state = XDM_QUERY;
  718.     break;
  719.     case XDM_COLLECT_BROADCAST_QUERY:
  720.     state = XDM_BROADCAST;
  721.     break;
  722.     case XDM_COLLECT_INDIRECT_QUERY:
  723.     state = XDM_INDIRECT;
  724.     break;
  725.     case XDM_AWAIT_REQUEST_RESPONSE:
  726.     state = XDM_START_CONNECTION;
  727.     break;
  728.     case XDM_AWAIT_MANAGE_RESPONSE:
  729.     state = XDM_MANAGE;
  730.     break;
  731.     case XDM_AWAIT_ALIVE_RESPONSE:
  732.     state = XDM_KEEPALIVE;
  733.     break;
  734.     }
  735.     send_packet();
  736. }
  737.  
  738. static
  739. restart()
  740. {
  741.     state = XDM_INIT_STATE;
  742.     timeOutRtx = 0;
  743.     send_packet();
  744. }
  745.  
  746. XdmcpCheckAuthentication (Name, Data, packet_type)
  747.     ARRAY8Ptr    Name, Data;
  748.     int    packet_type;
  749. {
  750.     return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
  751.         (AuthenticationName->length == 0 ||
  752.          (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
  753. }
  754.  
  755. XdmcpAddAuthorization (name, data)
  756.     ARRAY8Ptr    name, data;
  757. {
  758.     Bool    (*AddAuth)(), AddAuthorization();
  759.  
  760.     if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
  761.     AddAuth = AuthenticationFuncs->AddAuth;
  762.     else
  763.     AddAuth = AddAuthorization;
  764.     return (*AddAuth) ((unsigned short)name->length,
  765.                (char *)name->data,
  766.                (unsigned short)data->length,
  767.                (char *)data->data);
  768. }
  769.  
  770. /*
  771.  * from here to the end of this file are routines private
  772.  * to the state machine.
  773.  */
  774.  
  775. static
  776. get_xdmcp_sock()
  777. {
  778.     int soopts = 1;
  779.  
  780.     if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
  781.     XdmcpWarning("UDP socket creation failed");
  782. #ifdef SO_BROADCAST
  783.     else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, &soopts,
  784.     sizeof(soopts)) < 0)
  785.         XdmcpWarning("UDP set broadcast socket-option failed");
  786. #endif SO_BROADCAST
  787. }
  788.  
  789. static
  790. send_query_msg()
  791. {
  792.     XdmcpHeader    header;
  793.     Bool    broadcast = FALSE;
  794.     int        i;
  795.  
  796.     header.version = XDM_PROTOCOL_VERSION;
  797.     switch(state){
  798.     case XDM_QUERY:
  799.     header.opcode = (CARD16) QUERY; 
  800.     state = XDM_COLLECT_QUERY;
  801.     break;
  802.     case XDM_BROADCAST:
  803.     header.opcode = (CARD16) BROADCAST_QUERY;
  804.     state = XDM_COLLECT_BROADCAST_QUERY;
  805.     broadcast = TRUE;
  806.     break;
  807.     case XDM_INDIRECT:
  808.     header.opcode = (CARD16) INDIRECT_QUERY;
  809.     state = XDM_COLLECT_INDIRECT_QUERY;
  810.     break;
  811.     }
  812.     header.length = 1;
  813.     for (i = 0; i < AuthenticationNames.length; i++)
  814.     header.length += 2 + AuthenticationNames.data[i].length;
  815.  
  816.     XdmcpWriteHeader (&buffer, &header);
  817.     XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames);
  818.     if (broadcast)
  819.     {
  820.     int i;
  821.  
  822.     for (i = 0; i < NumBroadcastAddresses; i++)
  823.         XdmcpFlush (xdmcpSocket, &buffer, &BroadcastAddresses[i],
  824.             sizeof (struct sockaddr_in));
  825.     }
  826.     else
  827.     {
  828.     XdmcpFlush (xdmcpSocket, &buffer, &ManagerAddress,
  829.             sizeof (ManagerAddress));
  830.     }
  831. }
  832.  
  833. static
  834. recv_willing_msg(from, fromlen, length)
  835.     struct sockaddr_in    *from;
  836.     int            fromlen;
  837.     unsigned        length;
  838. {
  839.     ARRAY8    authenticationName;
  840.     ARRAY8    hostname;
  841.     ARRAY8    status;
  842.  
  843.     authenticationName.data = 0;
  844.     hostname.data = 0;
  845.     status.data = 0;
  846.     if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
  847.     XdmcpReadARRAY8 (&buffer, &hostname) &&
  848.     XdmcpReadARRAY8 (&buffer, &status))
  849.     {
  850.         if (length == 6 + authenticationName.length +
  851.               hostname.length + status.length)
  852.         {
  853.         switch (state)
  854.         {
  855.         case XDM_COLLECT_QUERY:
  856.             XdmcpSelectHost(from, fromlen, &authenticationName);
  857.             break;
  858.         case XDM_COLLECT_BROADCAST_QUERY:
  859.         case XDM_COLLECT_INDIRECT_QUERY:
  860.             XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status);
  861.             break;
  862.             }
  863.         }
  864.     }
  865.     XdmcpDisposeARRAY8 (&authenticationName);
  866.     XdmcpDisposeARRAY8 (&hostname);
  867.     XdmcpDisposeARRAY8 (&status);
  868. }
  869.  
  870. static
  871. send_request_msg()
  872. {
  873.     XdmcpHeader        header;
  874.     int            length;
  875.     int            i;
  876.     ARRAY8        authenticationData;
  877.  
  878.     header.version = XDM_PROTOCOL_VERSION;
  879.     header.opcode = (CARD16) REQUEST;
  880.  
  881.     length = 2;                        /* display number */
  882.     length += 1 + 2 * ConnectionTypes.length;        /* connection types */
  883.     length += 1;                    /* connection addresses */
  884.     for (i = 0; i < ConnectionAddresses.length; i++)
  885.     length += 2 + ConnectionAddresses.data[i].length;
  886.     authenticationData.length = 0;
  887.     authenticationData.data = 0;
  888.     if (AuthenticationFuncs)
  889.     {
  890.     (*AuthenticationFuncs->Generator) (AuthenticationData,
  891.                        &authenticationData,
  892.                         REQUEST);
  893.     }
  894.     length += 2 + AuthenticationName->length;        /* authentication name */
  895.     length += 2 + authenticationData.length;        /* authentication data */
  896.     length += 1;                    /* authorization names */
  897.     for (i = 0; i < AuthorizationNames.length; i++)
  898.     length += 2 + AuthorizationNames.data[i].length;
  899.     length += 2 + ManufacturerDisplayID.length;        /* display ID */
  900.     header.length = length;
  901.  
  902.     if (!XdmcpWriteHeader (&buffer, &header))
  903.     {
  904.     XdmcpDisposeARRAY8 (&authenticationData);
  905.     return;
  906.     }
  907.     XdmcpWriteCARD16 (&buffer, DisplayNumber);
  908.     XdmcpWriteARRAY16 (&buffer, &ConnectionTypes);
  909.     XdmcpWriteARRAYofARRAY8 (&buffer, &ConnectionAddresses);
  910.  
  911.     XdmcpWriteARRAY8 (&buffer, AuthenticationName);
  912.     XdmcpWriteARRAY8 (&buffer, &authenticationData);
  913.     XdmcpDisposeARRAY8 (&authenticationData);
  914.     XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames);
  915.     XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID);
  916.     if (XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen))
  917.     state = XDM_AWAIT_REQUEST_RESPONSE;
  918. }
  919.  
  920. static
  921. recv_accept_msg(length)
  922.     unsigned        length;
  923. {
  924.     CARD32  AcceptSessionID;
  925.     ARRAY8  AcceptAuthenticationName, AcceptAuthenticationData;
  926.     ARRAY8  AcceptAuthorizationName, AcceptAuthorizationData;
  927.  
  928.     if (state != XDM_AWAIT_REQUEST_RESPONSE)
  929.     return;
  930.     AcceptAuthenticationName.data = 0;
  931.     AcceptAuthenticationData.data = 0;
  932.     AcceptAuthorizationName.data = 0;
  933.     AcceptAuthorizationData.data = 0;
  934.     if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) &&
  935.     XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) &&
  936.     XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) &&
  937.     XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) &&
  938.     XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData))
  939.     {
  940.         if (length == 12 + AcceptAuthenticationName.length +
  941.                      AcceptAuthenticationData.length +
  942.                      AcceptAuthorizationName.length +
  943.                       AcceptAuthorizationData.length)
  944.         {
  945.         if (!XdmcpCheckAuthentication (&AcceptAuthenticationName,
  946.                       &AcceptAuthenticationData))
  947.         {
  948.         XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName);
  949.         }
  950.         /* if the authorization specified in the packet fails
  951.          * to be acceptable, enable the local addresses
  952.          */
  953.         if (!XdmcpAddAuthorization (&AcceptAuthorizationName,
  954.                     &AcceptAuthorizationData))
  955.         {
  956.         AddLocalHosts ();
  957.         }
  958.         SessionID = AcceptSessionID;
  959.             state = XDM_MANAGE;
  960.             send_packet();
  961.         }
  962.     }
  963.     XdmcpDisposeARRAY8 (&AcceptAuthenticationName);
  964.     XdmcpDisposeARRAY8 (&AcceptAuthenticationData);
  965.     XdmcpDisposeARRAY8 (&AcceptAuthorizationName);
  966.     XdmcpDisposeARRAY8 (&AcceptAuthorizationData);
  967. }
  968.  
  969. static
  970. recv_decline_msg(length)
  971.     unsigned        length;
  972. {
  973.     ARRAY8  Status, DeclineAuthenticationName, DeclineAuthenticationData;
  974.  
  975.     Status.data = 0;
  976.     DeclineAuthenticationName.data = 0;
  977.     DeclineAuthenticationData.data = 0;
  978.     if (XdmcpReadARRAY8 (&buffer, &Status) &&
  979.     XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) &&
  980.     XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData))
  981.     {
  982.         if (length == 6 + Status.length +
  983.                     DeclineAuthenticationName.length +
  984.                      DeclineAuthenticationData.length &&
  985.         XdmcpCheckAuthentication (&DeclineAuthenticationName,
  986.                       &DeclineAuthenticationData))
  987.         {
  988.         XdmcpFatal ("Session declined", &Status);
  989.         }
  990.     }
  991.     XdmcpDisposeARRAY8 (&Status);
  992.     XdmcpDisposeARRAY8 (&DeclineAuthenticationName);
  993.     XdmcpDisposeARRAY8 (&DeclineAuthenticationData);
  994. }
  995.  
  996. static
  997. send_manage_msg()
  998. {
  999.     XdmcpHeader    header;
  1000.  
  1001.     header.version = XDM_PROTOCOL_VERSION;
  1002.     header.opcode = (CARD16) MANAGE;
  1003.     header.length = 8 + DisplayClass.length;
  1004.  
  1005.     if (!XdmcpWriteHeader (&buffer, &header))
  1006.     return;
  1007.     XdmcpWriteCARD32 (&buffer, SessionID);
  1008.     XdmcpWriteCARD16 (&buffer, DisplayNumber);
  1009.     XdmcpWriteARRAY8 (&buffer, &DisplayClass);
  1010.     state = XDM_AWAIT_MANAGE_RESPONSE;
  1011.     XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen);
  1012. }
  1013.  
  1014. static
  1015. recv_refuse_msg(length)
  1016.     unsigned        length;
  1017. {
  1018.     CARD32  RefusedSessionID;
  1019.  
  1020.     if (state != XDM_AWAIT_MANAGE_RESPONSE)
  1021.     return;
  1022.     if (length != 4)
  1023.     return;
  1024.     if (XdmcpReadCARD32 (&buffer, &RefusedSessionID))
  1025.     {
  1026.     if (RefusedSessionID == SessionID)
  1027.     {
  1028.             state = XDM_START_CONNECTION;
  1029.             send_packet();
  1030.     }
  1031.     }
  1032. }
  1033.  
  1034. static
  1035. recv_failed_msg(length)
  1036.     unsigned        length;
  1037. {
  1038.     CARD32  FailedSessionID;
  1039.     ARRAY8  Status;
  1040.  
  1041.     if (state != XDM_AWAIT_MANAGE_RESPONSE)
  1042.     return;
  1043.     Status.data = 0;
  1044.     if (XdmcpReadCARD32 (&buffer, &FailedSessionID) &&
  1045.     XdmcpReadARRAY8 (&buffer, &Status))
  1046.     {
  1047.         if (length == 5 + Status.length &&
  1048.         SessionID == FailedSessionID)
  1049.     {
  1050.         XdmcpFatal ("Session failed", &Status);
  1051.     }
  1052.     }
  1053.     XdmcpDisposeARRAY8 (&Status);
  1054. }
  1055.  
  1056. static
  1057. send_keepalive_msg()
  1058. {
  1059.     XdmcpHeader    header;
  1060.  
  1061.     header.version = XDM_PROTOCOL_VERSION;
  1062.     header.opcode = (CARD16) KEEPALIVE;
  1063.     header.length = 6;
  1064.  
  1065.     XdmcpWriteHeader (&buffer, &header);
  1066.     XdmcpWriteCARD16 (&buffer, DisplayNumber);
  1067.     XdmcpWriteCARD32 (&buffer, SessionID);
  1068.  
  1069.     state = XDM_AWAIT_ALIVE_RESPONSE;
  1070.     XdmcpFlush (xdmcpSocket, &buffer, &req_sockaddr, req_socklen);
  1071. }
  1072.  
  1073. static
  1074. recv_alive_msg (length)
  1075.     unsigned        length;
  1076. {
  1077.     CARD8   SessionRunning;
  1078.     CARD32  AliveSessionID;
  1079.  
  1080.     if (state != XDM_AWAIT_ALIVE_RESPONSE)
  1081.     return;
  1082.     if (length != 5)
  1083.     return;
  1084.     if (XdmcpReadCARD8 (&buffer, &SessionRunning) &&
  1085.     XdmcpReadCARD32 (&buffer, &AliveSessionID))
  1086.     {
  1087.         if (SessionRunning && AliveSessionID == SessionID)
  1088.         {
  1089.         /* backoff dormancy period */
  1090.         state = XDM_RUN_SESSION;
  1091.         if (TimeSinceLastInputEvent() > keepaliveDormancy * 1000)
  1092.             keepaliveDormancy = MIN(keepaliveDormancy << 1, XDM_MAX_DORMANCY);
  1093.         timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
  1094.         }
  1095.     else
  1096.         {
  1097.         XdmcpDeadSession ("Alive respose indicates session dead");
  1098.         }
  1099.     }
  1100. }
  1101.  
  1102. static 
  1103. XdmcpFatal (type, status)
  1104.     char    *type;
  1105.     ARRAY8Ptr    status;
  1106. {
  1107.     extern void AbortDDX();
  1108.  
  1109.     printf("XDMCP fatal error: %s %*.*s\n", type,
  1110.        status->length, status->length, status->data);
  1111.     AbortDDX ();
  1112.     exit (1);
  1113. }
  1114.  
  1115. static 
  1116. XdmcpWarning(str)
  1117.     char *str;
  1118. {
  1119.     printf("XDMCP warning: %s\n", str);
  1120. }
  1121.  
  1122. static
  1123. get_manager_by_name(argc, argv, i)
  1124.     int        argc, i;
  1125.     char    **argv;
  1126. {
  1127.     struct hostent *hep;
  1128.  
  1129.     if (i == argc)
  1130.     {
  1131.     printf("Xserver: missing host name in command line\n");
  1132.     exit(1);
  1133.     }
  1134.     if (!(hep = gethostbyname(argv[i])))
  1135.     {
  1136.     printf("Xserver: unknown host: %s\n", argv[i]);
  1137.     exit(1);
  1138.     }
  1139.     if (hep->h_length == sizeof (struct in_addr))
  1140.     {
  1141.     bcopy(hep->h_addr, &ManagerAddress.sin_addr, hep->h_length);
  1142.     ManagerAddress.sin_family = AF_INET;
  1143.     ManagerAddress.sin_port = htons (xdm_udp_port);
  1144.     }
  1145.     else
  1146.     {
  1147.     printf ("Xserver: host on strange network %s\n", argv[i]);
  1148.     exit (1);
  1149.     }
  1150. }
  1151. #endif /* XDMCP */
  1152. @
  1153.